#ifndef CLIPBOARD_SHARE_WINDOW_H
#define CLIPBOARD_SHARE_WINDOW_H

#include <vector>
#include <set>
#include <string>
#include <map>
#include <list>
#include <functional>
#include <mutex>

#include <windows.h>

#include "DataObject.h"
#include "Share.h"
#include "ShareTransport.h"

#define CBS_WIN_CLASS_NAME L"ClipboardShareWnd"
#define CLIPBOARD_PUT_FILES_MSG L"ClipboardPutFiles"
#define DELETE_SHARE_NAME_MSG L"DeleteShareName"
#define SYNC_CLIPBOARD_DATA_TO_HOST_MSG L"SyncClipboardDataToHost"

#define CBS_WND_WIDTH 600
#define CBS_WND_HEIGHT 600

class ClipboardShareWindow {
public:
    explicit ClipboardShareWindow(
        std::function<void()> fetchAndSendClipboardData,
        std::function<void(WPARAM, LPARAM)> devChangeNotify,
        std::function<std::string(FileShareList&)> fileShareUpdate,
        std::function<void(const char*, DWORD)> sendShareName);
    ~ClipboardShareWindow();
    DWORD Init();
    void Destroy();
    HANDLE GetWaitHandle();
    BOOL OpenClipboard();
    BOOL CloseClipboard();
    BOOL EmptyClipboard();
    DWORD ClipboardFormatToCustomFormat(DWORD dwFormat);
    ShareSendProcess* GetClipboardShareSendProcess(DWORD dwFormat);
    BOOL StartClipboardListen();
    BOOL StopClipboardListen();
    void PutFilesToClipboard(LPCSTR share);
    void DeleteShareName(LPCSTR shareName);
    void SyncClipboardDataToHost();
    void SetClipboardUpdateFlag();
    HDEVNOTIFY RegisterHandleNotify(HANDLE handle);

private:
    static DWORD WINAPI WindowThread(ClipboardShareWindow* ptr);
    DWORD CbsWndThread();
    static LRESULT CALLBACK ClipboardShareWndProc(
        HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT HandleRegisterMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    BOOL RegisterWindowClass(PCWSTR pszClassName, PCWSTR pszMenuName,
                             WNDPROC lpfnWndProc);
    BOOL ProcessPutFilesToClipboard(LPCSTR share);
    BOOL SetOleClipboard(IDataObject* obj, LPCSTR share);
    void ProcessDeleteShareName(LPCSTR shareName);
    HDEVNOTIFY RegisterInterfaceNotify(GUID InterfaceClassGuid);

    std::function<void()> m_fetchAndSendClipboardData;
    std::function<void(WPARAM, LPARAM)> m_devChangeNotify;
    std::function<std::string(FileShareList&)> m_fileShareUpdate;
    std::function<void(const char*, DWORD)> m_sendShareName;
    BOOL m_bInitialised;
    HWND m_hWnd;
    HINSTANCE m_hInst;
    HANDLE m_hWindowThread;
    HANDLE m_hCompleteInitCbs;
    std::mutex m_mutex;
    HDEVNOTIFY m_portNotify;
    HDEVNOTIFY m_vioFsNotify;
    std::atomic<BOOL> m_clipboardUpdateFlag;
};

#endif // CLIPBOARD_WINDOW_H
